Imports System.Drawing

Namespace Controls

    Friend Class libGridBasic
        Inherits DataGridView
        Public Property DoubleBuffering() As Boolean
            Get
                Return Me.DoubleBuffered
            End Get
            Set(ByVal value As Boolean)
                DoubleBuffered = value
            End Set
        End Property
    End Class

    Friend Class libGrid
        Inherits DataGridView
        Implements DataStream.IStreamRecieve

        Private m_TraceWidth As Single = 1
        Private m_TraceColour As Color = Color.Green
        Private m_TraceX As Single = -1
        Private m_TraceY As Single = -1

        Private m_EmuTraceWidth As Single = 1
        Private m_EmuTraceColour As Color = Color.Red
        Private m_EmuTracePts As Point() = Nothing

        Private m_rowDesc As String = ""
        Private m_colDesc As String = ""
        Private m_tag As New TraceTag
        Private m_Table As BikiSoft.Table
        Private m_Data() As Byte

        ''' <remarks>Array of pointf's to display over the grid for a trace callback display</remarks>
        Private m_TraceOverlayPoints() As PointF = Nothing
        Private m_tracePath As Drawing2D.GraphicsPath = Nothing
        Private m_TraceOverlay As Image
        Private m_TraceOverlayStrings() As String = Nothing
        'Private mGraphicManager As BufferedGraphicsContext
        'Private mLegendBuffer As BufferedGraphics

        Sub New()
            MyBase.New()
            Me.DefaultCellStyle = New DataGridViewCellStyle
            'SetStyle(ControlStyles.UserPaint, True)
        End Sub
        Friend Sub Clear()
            Me.Rows.Clear()
            m_TraceX = -1
            m_TraceY = -1
            m_EmuTracePts = Nothing
            m_rowDesc = ""
            m_colDesc = ""
            m_Data = Nothing
            m_Table = Nothing
            m_tag = New TraceTag
            m_TraceOverlayPoints = Nothing
        End Sub
        Public Property DoubleBuffering() As Boolean
            Get
                Return Me.DoubleBuffered
            End Get
            Set(ByVal value As Boolean)
                DoubleBuffered = value
            End Set
        End Property

        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            Dim recTrace As Rectangle = Nothing
            MyBase.OnPaint(e)
            Dim g As Graphics = e.Graphics
            Debug.Print("Grid is re-drawing")
            ' draw trace overlay
            If Not IsNothing(m_TraceOverlayPoints) AndAlso m_TraceOverlayPoints.Length > 0 Then
                'Dim fPath As New Drawing2D.GraphicsPath
                'fPath.FillMode = FillMode.Winding
                'fPath.AddLines(m_TraceOverlayPoints)
                'Dim trans As New Matrix()
                ''     trans.Translate(Me.RowHeadersWidth, Me.ColumnHeadersHeight)

                '' Scale to cell width and height
                'trans.Scale(Me.Item(0, 0).Size.Width, Me.Item(0, 0).Size.Height)

                '' Translate to offset of first cell


                '' transform the path
                'fPath.Transform(trans)

                'Dim p As Pen = New Pen(Color.FromArgb(80, m_TraceColour), Me(0, 0).Size.Height)
                'g.DrawPath(p, Me.m_tracePath)
                'p.Dispose()

                g.DrawImage(m_TraceOverlay, 0.0!, 0.0!)
            End If
            If Me.RowCount >= 1 Or Me.ColumnCount >= 1 Then
                If m_TraceX >= 0 Or m_TraceY >= 0 Then
                    If m_TraceX = -1 Then m_TraceX = 0
                    If m_TraceY = -1 Then m_TraceY = 0

                    g.Clip = New Region(e.ClipRectangle)
                    TraceDraw(g)
                End If
            End If
        End Sub

        Protected Overrides Sub OnRowPostPaint(ByVal e As System.Windows.Forms.DataGridViewRowPostPaintEventArgs)
            MyBase.OnRowPostPaint(e)
            If e.RowIndex = 0 Then DescDraw(e.Graphics)

            Try
                ' Paint the row number on the row header.
                ' The using statement automatically disposes the brush.
                If IsNothing(m_Table) Then
                    Using b As SolidBrush = _
                      New SolidBrush(Me.RowHeadersDefaultCellStyle.ForeColor)
                        e.Graphics.DrawString( _
                          Hex(e.RowIndex.ToString(System.Globalization.CultureInfo.CurrentUICulture)), _
                          New System.Drawing.Font("Courier New", 8), _
                          b, _
                          e.RowBounds.Location.X + 5, _
                          e.RowBounds.Location.Y + 4)
                    End Using

                ElseIf Not IsNothing(m_Table) Then
                    Dim s_return() As String = m_Table.getHeightDisplay(m_Data)
                    If Not IsNothing(s_return) Then
                        Using b As SolidBrush = _
                            New SolidBrush(Me.RowHeadersDefaultCellStyle.ForeColor)
                            e.Graphics.DrawString( _
                            s_return(e.RowIndex).ToString(System.Globalization.CultureInfo.CurrentUICulture), _
                            New System.Drawing.Font("Courier New", 8), _
                            b, _
                            e.RowBounds.Location.X + 5, _
                            e.RowBounds.Location.Y + 4)
                        End Using
                    Else
                        Using b As SolidBrush = _
                        New SolidBrush(Me.RowHeadersDefaultCellStyle.ForeColor)
                            e.Graphics.DrawString( _
                            Hex((e.RowIndex * m_Table.Width).ToString), _
                            New System.Drawing.Font("Courier New", 8), _
                            b, _
                            e.RowBounds.Location.X + 5, _
                            e.RowBounds.Location.Y + 4)
                        End Using
                    End If
                End If
            Catch
            End Try
        End Sub

        Friend Shadows Property tag() As TraceTag
            Get
                Return m_tag
            End Get
            Set(ByVal value As TraceTag)
                m_tag = value
            End Set
        End Property
        Public Sub TraceDraw()
            TraceDraw(Me.CreateGraphics)
        End Sub
        Public Sub TraceDraw(ByVal g As Graphics)
            If Me.RowCount >= 1 Or Me.ColumnCount >= 1 Then
                If m_TraceX >= 0 Or m_TraceY >= 0 Then
                    If m_TraceX = -1 Then m_TraceX = 0
                    If m_TraceY = -1 Then m_TraceY = 0

                    Dim recTrace As New Rectangle( _
                        (m_TraceX * Me.Item(0, 0).Size.Width) + Me.RowHeadersWidth, _
                        (m_TraceY * Me.Item(0, 0).Size.Height) + Me.ColumnHeadersHeight, _
                        Me.Item(0, 0).Size.Width, _
                        Me.Item(0, 0).Size.Height)
                    g.DrawRectangle(New Pen(m_TraceColour, m_TraceWidth), recTrace)


                    If Not IsNothing(Me.m_TraceOverlayStrings) Then
                        Dim fYcount As UInt16
                        For Each str As String In m_TraceOverlayStrings
                            If str <> "" Then fYcount += 1
                        Next
                        Dim f_upperPoint As Point

                        If (m_TraceY + 1) > (Me.RowCount / 2) Then ' Bottom half
                            If (m_TraceX + 1) > Me.ColumnCount / 2 Then ' Bottom, right
                                f_upperPoint.X = recTrace.X - 100
                                f_upperPoint.Y = recTrace.Y - ((fYcount * 12) + 10)
                            Else ' Bottom, left
                                f_upperPoint.X = recTrace.X + recTrace.Width
                                f_upperPoint.Y = recTrace.Y - ((fYcount * 12) + 10)
                            End If
                        Else ' Top half
                            If (m_TraceX + 1) > (Me.ColumnCount / 2) Then ' Top, right
                                f_upperPoint.X = recTrace.X - 100
                                f_upperPoint.Y = recTrace.Y + recTrace.Height
                            Else ' Top, left
                                f_upperPoint.X = recTrace.X + recTrace.Width
                                f_upperPoint.Y = recTrace.Y + recTrace.Height
                            End If
                        End If

                        g.FillRectangle(New SolidBrush(Color.FromArgb(220, Color.White)), New Rectangle(f_upperPoint.X, f_upperPoint.Y, 100, (fYcount * 12) + 10))
                        g.DrawRectangle(New Pen(m_TraceColour), New Rectangle(f_upperPoint.X, f_upperPoint.Y, 100, (fYcount * 12) + 10))
                        g.TextContrast = 4
                        Dim stringFormat As New StringFormat
                        stringFormat.Alignment = StringAlignment.Near
                        stringFormat.LineAlignment = StringAlignment.Center
                        stringFormat.SetTabStops(40, New Single() {5, 5, 5})
                        g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
                        Dim b As New SolidBrush(Color.Black)
                        fYcount = 0
                        For Each str As String In m_TraceOverlayStrings
                            If str <> "" Then
                                g.DrawString(str, New Font(Me.Font, FontStyle.Regular), New SolidBrush(Color.Black), f_upperPoint.X + 5, f_upperPoint.Y + 5 + (12 * fYcount) + 5, stringFormat)
                                fYcount += 1
                            End If
                        Next
                        b.Dispose()
                    End If


                    If Not IsNothing(m_EmuTracePts) Then
                        Dim f_rects As Rectangle()
                        ReDim f_rects(UBound(m_EmuTracePts))
                        For i As Integer = 0 To UBound(m_EmuTracePts)
                            f_rects(i) = New Rectangle( _
                                m_EmuTracePts(i).X * Me.Item(0, 0).Size.Width + Me.RowHeadersWidth, _
                                m_EmuTracePts(i).Y * Me.Item(0, 0).Size.Height + Me.ColumnHeadersHeight, _
                                Me.Item(0, 0).Size.Width, _
                                Me.Item(0, 0).Size.Height)
                        Next
                        g.DrawRectangles(New Pen(m_EmuTraceColour, m_EmuTraceWidth), f_rects)
                    End If
                End If
            End If
        End Sub
        Public Sub TraceInvalidate()
            If Me.RowCount >= 1 Or Me.ColumnCount >= 1 Then
                If m_TraceX >= 0 Or m_TraceY >= 0 Then
                    If m_TraceX = -1 Then m_TraceX = 0
                    If m_TraceY = -1 Then m_TraceY = 0

                    Me.Invalidate(New Region(New Rectangle( _
                        m_TraceX * Me.Item(0, 0).Size.Width + Me.RowHeadersWidth - 1, _
                        m_TraceY * Me.Item(0, 0).Size.Height + Me.ColumnHeadersHeight - 1, _
                        Me.Item(0, 0).Size.Width + 3, _
                        Me.Item(0, 0).Size.Height + 3)))

                    If Not IsNothing(m_EmuTracePts) Then
                        For i As Integer = 0 To UBound(m_EmuTracePts)
                            Me.Invalidate(New Region(New Rectangle( _
                                m_EmuTracePts(i).X * Me.Item(0, 0).Size.Width + Me.RowHeadersWidth - 1, _
                                m_EmuTracePts(i).Y * Me.Item(0, 0).Size.Height + Me.ColumnHeadersHeight - 1, _
                                Me.Item(0, 0).Size.Width + 3, _
                                Me.Item(0, 0).Size.Height + 3)))
                        Next
                    End If
                End If
            End If
        End Sub
        Private Sub DescDraw(ByVal g As Graphics)
            Dim f_colFormat As New StringFormat
            Dim f_rowFormat As New StringFormat
            Dim f_font As New System.Drawing.Font("Courier New", 9, FontStyle.Regular, GraphicsUnit.Pixel)
            Using b As SolidBrush = New SolidBrush(Me.RowHeadersDefaultCellStyle.ForeColor)

                f_colFormat.LineAlignment = StringAlignment.Near ' Horiz
                f_colFormat.Alignment = StringAlignment.Far ' Vertical

                f_rowFormat.LineAlignment = StringAlignment.Far
                f_rowFormat.Alignment = StringAlignment.Near

                If m_rowDesc <> "" Then g.DrawString(m_rowDesc, f_font, b, 1, Me.ColumnHeadersHeight - 1, f_rowFormat)
                If m_colDesc <> "" Then g.DrawString(m_colDesc, f_font, b, Me.RowHeadersWidth - 1, 1, f_colFormat)
            End Using
        End Sub
        Private Sub DescDraw()
            DescDraw(Me.CreateGraphics)
        End Sub
        Public Property ColumnDescription() As String
            Get
                Return m_colDesc
            End Get
            Set(ByVal value As String)
                m_colDesc = value
                DescDraw()
            End Set
        End Property
        Public Property RowDescription() As String
            Get
                Return m_rowDesc
            End Get
            Set(ByVal value As String)
                m_rowDesc = value
                DescDraw()
            End Set
        End Property

        '<Description("Get or Set the colour of the first trace")> _
        Public Property TraceColour() As Color
            Get
                Return m_TraceColour
            End Get
            Set(ByVal value As Color)
                m_TraceColour = value
            End Set
        End Property
        ' <Description("Get or Set the X-Y co-ordinate for the trace")> _
        Public Property TracePoint() As PointF
            Get
                Return New PointF(m_TraceX, m_TraceY)
            End Get
            Set(ByVal value As PointF)
                If value.X <> m_TraceX Or value.Y <> m_TraceY Then
                    TraceInvalidate()
                    m_TraceX = value.X
                    m_TraceY = value.Y
                    If IsNothing(m_TraceOverlayStrings) Then
                        TraceDraw()
                    Else
                        m_TraceOverlayStrings = Nothing
                        Me.Invalidate()
                        TraceDraw()
                    End If
                End If
            End Set
        End Property
        Public Property TraceWidth() As Single
            Get
                Return m_TraceWidth
            End Get
            Set(ByVal value As Single)
                m_TraceWidth = value
            End Set
        End Property

        Public Property EmuTraceWidth() As Single
            Get
                Return m_EmuTraceWidth
            End Get
            Set(ByVal value As Single)
                m_EmuTraceWidth = value
            End Set
        End Property
        Public Property EmuTraceColour() As Color
            Get
                Return m_EmuTraceColour
            End Get
            Set(ByVal value As Color)
                m_EmuTraceColour = value
            End Set
        End Property
        Public Property EmuTracePoints() As Point()
            Get
                Return m_EmuTracePts
            End Get
            Set(ByVal value As Point())
                TraceInvalidate()
                m_EmuTracePts = value
                TraceDraw()
            End Set
        End Property
        Friend ReadOnly Property Table() As Table
            Get
                Return m_Table
            End Get
        End Property

        Friend Sub setTable(ByRef iTable As Table)
            m_Table = iTable
        End Sub
        Friend Sub setData(ByRef iData As Byte())
            m_Data = iData
        End Sub

        Friend Sub populate(ByRef iTable As Table, ByRef iData As Byte())
            m_Table = iTable
            m_Data = iData
            Me.populate()
        End Sub
        Friend Sub populate()
            Me.m_TraceOverlayStrings = Nothing
            Me.m_TraceOverlayPoints = Nothing

            If Not IsNothing(m_Table.getWidthScale.Description) Then
                Me.ColumnDescription = m_Table.getWidthScale.Description.ToolTip
            Else
                Me.ColumnDescription = ""
            End If
            If Not IsNothing(m_Table.getHeightScale.Description) Then
                Me.RowDescription = m_Table.getHeightScale.Description.ToolTip
            Else
                Me.RowDescription = ""
            End If
            If Not IsNothing(m_Table) And Not IsNothing(m_Data) Then
                Dim tm_width As Short = m_Table.Width
                Dim tm_height As Short = m_Table.Height
                Dim f_size As Byte
                Select Case (m_Table.ByteSize)
                    Case 1
                        f_size = 36
                    Case 2
                        f_size = 54
                    Case 4
                        f_size = 54
                End Select
                Dim tm_widthDisp As String() = Nothing
                If Not IsNothing(m_Table.getWidthScale) Then
                    tm_widthDisp = m_Table.getWidthDisplay(m_Data)
                End If

                If m_Table.AxisSwap Then
                    tm_width = m_Table.Height
                    tm_height = m_Table.Width
                End If

                Me.Rows.Clear()
                Me.Columns.Clear()
                'Me.RowCount = 0
                'Me.ColumnCount = 0
                Select Case m_Table.Scheme
                    Case DisplayScheme.BK_SCH_BYTE
                        If m_Table.Multiplier Mod 1 <> 0 Then
                            Me.RowsDefaultCellStyle.Format = "N1"
                            Me.AlternatingRowsDefaultCellStyle.Format = "N1"
                            Me.DefaultCellStyle.Format = "N1"
                        Else
                            Me.RowsDefaultCellStyle.Format = "N0"
                            Me.AlternatingRowsDefaultCellStyle.Format = "N0"
                            Me.DefaultCellStyle.Format = "N0"
                        End If
                    Case DisplayScheme.BK_SCH_EARLY
                        If m_Table.Multiplier Mod 1 <> 0 Then
                            Me.RowsDefaultCellStyle.Format = "N1"
                            Me.DefaultCellStyle.Format = "N1"
                            Me.AlternatingRowsDefaultCellStyle.Format = "N1"
                        Else
                            Me.RowsDefaultCellStyle.Format = "N0"
                            Me.DefaultCellStyle.Format = "N0"
                            Me.AlternatingRowsDefaultCellStyle.Format = "N0"
                        End If
                    Case DisplayScheme.BK_SCH_IGN
                        Me.RowsDefaultCellStyle.Format = "N0"
                        Me.DefaultCellStyle.Format = "N0"
                        Me.AlternatingRowsDefaultCellStyle.Format = "N0"
                    Case DisplayScheme.BK_SCH_LATE
                        If m_Table.Multiplier Mod 1 <> 0 Then
                            Me.RowsDefaultCellStyle.Format = "N1"
                            Me.DefaultCellStyle.Format = "N1"
                            Me.AlternatingRowsDefaultCellStyle.Format = "N1"
                        Else
                            Me.RowsDefaultCellStyle.Format = "N0"
                            Me.DefaultCellStyle.Format = "N0"
                            Me.AlternatingRowsDefaultCellStyle.Format = "N0"
                        End If
                    Case DisplayScheme.BK_SCH_WORD
                        Me.RowsDefaultCellStyle.Format = ""
                        Me.DefaultCellStyle.Format = ""
                        Me.AlternatingRowsDefaultCellStyle.Format = ""
                    Case Else
                        Me.RowsDefaultCellStyle.Format = ""
                        Me.DefaultCellStyle.Format = ""
                        Me.AlternatingRowsDefaultCellStyle.Format = ""
                End Select

                Me.tag.Address = m_Table.Address
                Dim colGridNew As Controls.LibGridColumn
                For i As Short = 0 To tm_width - 1
                    colGridNew = New Controls.LibGridColumn()
                    colGridNew.Name = Str(i)
                    If Not IsNothing(tm_widthDisp) Then colGridNew.HeaderText = Trim(tm_widthDisp(i))
                    Me.Columns.Add(colGridNew)
                    Me.Columns(i).SortMode = DataGridViewColumnSortMode.NotSortable
                    Me.Columns(i).Width = f_size
                    Me.Columns(i).DefaultCellStyle = New DataGridViewCellStyle(Me.DefaultCellStyle)
                Next
                Me.ColumnCount = tm_width
                Me.RowCount = tm_height

                Dim tm_x As Short
                Dim tm_y As Short
                For x As Short = 0 To m_Table.Width - 1
                    For y As Short = 0 To m_Table.Height - 1
                        tm_y = y
                        tm_x = x
                        If m_Table.HeightInvert Then tm_y = m_Table.Height - 1 - y
                        If m_Table.WidthInvert Then tm_x = m_Table.Width - 1 - x
                        If m_Table.AxisSwap Then Swap(tm_x, tm_y)
                        Me.Item(tm_x, tm_y) = New Controls.libGridCell()
                        Me.Item(tm_x, tm_y).Style.Format = Me.DefaultCellStyle.Format
                        CType(Me.Item(tm_x, tm_y), Controls.libGridCell).setData(m_Data, m_Table.Address + (y * m_Table.Width * m_Table.ByteSize) + (x * m_Table.ByteSize), m_Table)
                    Next
                Next
            End If
            '  Catch
            'Me.RowCount = 1
            'Me.ColumnCount = 1
            'Me.Columns(0).Width = 200
            'Me.Item(0, 0) = New DataGridViewTextBoxCell
            'Me.Item(0, 0).Value = "Error displaying grid"
            'End Try
        End Sub
        ''' <summary>
        ''' Sets the current Dataloging trace overlay for the table to display.
        ''' </summary>
        ''' <param name="log">Complete Datalog stream</param>
        ''' <param name="startX">Start Index</param>
        ''' <param name="endX">End Index</param>
        ''' <remarks></remarks>
        Friend Sub setTraceOverlay(ByRef log As DataStream.Stream, ByVal startX As Long, ByVal endX As Long)
            If Not IsNothing(log) And Not IsNothing(m_Data) And Not IsNothing(m_Table) AndAlso startX < endX Then
                ReDim m_TraceOverlayPoints((endX - startX - 1) * 2)

                For i As Integer = 0 To (endX - startX - 1) * 2 Step 2
                    Dim point As PointF = m_Table.TracePoint(m_Data, log)
                    Dim point2 As New PointF(point.X, point.Y)
                    point2.X += 1
                    point2.Y += 0.5
                    point.Y += 0.5
                    m_TraceOverlayPoints(i) = point
                    m_TraceOverlayPoints(i + 1) = point2
                Next
                Me.Refresh()
            End If
        End Sub
        Friend Sub setTraceOverlayStrings(ByVal Strings As String())
            'm_TraceOverlayStrings = Nothing
            m_TraceOverlayStrings = Strings
            Me.Refresh()
        End Sub
        Friend Sub setTracePoint(ByVal stream As DataStream.Stream)
            If Not IsNothing(stream) Then
                TracePoint = m_Table.TracePoint(m_Data, stream)
            End If
        End Sub

        Public ReadOnly Property RecieverType() As DataStream.StreamRecieveType Implements DataStream.IStreamRecieve.RecieverType
            Get
                Return DataStream.StreamRecieveType.eStreamConsumeOnly
            End Get
        End Property

        'Public Shadows Property Item(ByVal colIndex As Integer, ByVal rowIndex As Integer) As libGridCell
        '    Get
        '        If rowIndex < 0 Or rowIndex > Me.RowCount Then
        '            Throw New Exception("Row Index out of bounds, must be >=0 or <= Rowcount")
        '            Return Nothing
        '        End If
        '        If colIndex < 0 Or colIndex > Me.ColumnCount Then
        '            Throw New Exception("Col Index out of bounds, must be >=0 or <= Colcount")
        '            Return Nothing
        '        End If
        '        Return CType(MyBase.Item(colIndex, rowIndex), Controls.libGridCell)
        '    End Get
        '    Set(ByVal value As libGridCell)
        '        If rowIndex < 0 Or rowIndex > Me.RowCount Then
        '            Throw New Exception("Row Index out of bounds, must be >=0 or <= Rowcount")
        '        End If
        '        If colIndex < 0 Or colIndex > Me.ColumnCount Then
        '            Throw New Exception("Col Index out of bounds, must be >=0 or <= Colcount")
        '        End If
        '        MyBase.Item(colIndex, rowIndex) = value
        '    End Set
        'End Property

        ''' <summary>
        ''' Generates the Stream Overlay for the grid
        ''' </summary>
        ''' <param name="streamLog"></param>
        ''' <remarks></remarks>
        Public Sub GenerateStreamOverlay(ByVal streamLog As DataStream.StreamLog)
            If Not IsNothing(m_Table) AndAlso Not IsNothing(m_Data) AndAlso Not IsNothing(streamLog) AndAlso streamLog.Count > 0 Then
                Dim start As Integer = streamLog.RestrictStart
                Dim finish As Integer = streamLog.RestrictEnd

                If start = -1 Then start = 0
                If finish = -1 Then finish = streamLog.Count - 1

                If finish - start > 0 Then

                    ReDim m_TraceOverlayPoints(finish - start)

                    For nCnt As Integer = start To finish
                        m_TraceOverlayPoints(nCnt - start) = m_Table.TracePoint(m_Data, streamLog(nCnt))

                        If m_TraceOverlayPoints(nCnt - start).X = -1 Then m_TraceOverlayPoints(nCnt - start).X = 0
                        If m_TraceOverlayPoints(nCnt - start).Y = -1 Then m_TraceOverlayPoints(nCnt - start).Y = 0

                        m_TraceOverlayPoints(nCnt - start).X *= Me(0, 0).Size.Width
                        m_TraceOverlayPoints(nCnt - start).Y *= Me(0, 0).Size.Height

                        m_TraceOverlayPoints(nCnt - start).Y += Me.ColumnHeadersHeight * 1.5
                        m_TraceOverlayPoints(nCnt - start).X += Me.RowHeadersWidth * 1.5
                    Next

                    Me.m_tracePath = New Drawing2D.GraphicsPath
                    m_tracePath.FillMode = FillMode.Alternate
                    m_tracePath.AddLines(m_TraceOverlayPoints)

                    m_TraceOverlay = New Bitmap(Me.Bounds.Width, Me.Bounds.Height)
                    Dim g As Graphics = Graphics.FromImage(m_TraceOverlay)

                    g.Clear(Color.Transparent)
                    Dim p As Pen = New Pen(Color.FromArgb(80, m_TraceColour), Me(0, 0).Size.Height)
                    g.DrawPath(p, Me.m_tracePath)
                    p.Dispose()
                    g.Dispose()

                End If

                Me.Refresh()
            End If
        End Sub
        ''' <summary>
        ''' Clears the Stream overlay for the grid
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub ClearStreamOverlay()
            If Not m_TraceOverlayPoints Is Nothing Then
                m_TraceOverlayPoints = Nothing
                m_tracePath.Dispose()
                m_tracePath = Nothing
                Me.Refresh()
            End If
        End Sub
        Public Sub RecieveStream(ByVal Stream As DataStream.Stream) Implements DataStream.IStreamRecieve.RecieveStream
            ' Get the live trace
            If Not IsNothing(Me.m_Table) _
            AndAlso Not IsNothing(m_Data) Then
                TracePoint = m_Table.TracePoint(m_Data, Stream)
            End If

            ' Get the emulator trace
            If Stream.contains("EmulatorAddress") _
            AndAlso Stream.contains("EmulatorLast") Then
                Dim Addresses() As Integer = CType(Stream("EmulatorAddress").Value, Integer())
                Dim Points(Addresses.Length - 1) As Point
                Dim Count As Integer = 0

                For Each address As Integer In Addresses
                    If address >= m_Table.Address _
                    AndAlso address <= m_Table.Address + m_Table.Length Then
                        address -= m_Table.Address
                        Points(Count).X = address Mod m_Table.Width
                        Points(Count).Y = address \ m_Table.Width
                        If m_Table.WidthInvert Then Points(Count).X = (m_Table.Width - 1) - Points(Count).X
                        If m_Table.HeightInvert Then Points(Count).Y = (m_Table.Height - 1) - Points(Count).Y
                        If m_Table.AxisSwap Then Swap(Points(Count))
                        Count += 1
                    End If
                Next

                ReDim Preserve Points(Count - 1)

                Me.EmuTracePoints = Points
            End If

        End Sub

        Public Event RequestRefresh(ByVal sender As Object, ByVal e As System.EventArgs) Implements DataStream.IStreamRecieve.RequestRefresh

        Public Event Restrict(ByVal sender As Object, ByVal e As DataStream.StreamRestrictEventArgs) Implements DataStream.IStreamRecieve.Restrict

        Public Event Seek(ByVal sender As Object, ByVal e As DataStream.StreamSeekEventArgs) Implements DataStream.IStreamRecieve.Seek

        Public Event Close(ByVal sender As Object, ByVal e As System.EventArgs) Implements DataStream.IStreamRecieve.Close

        Public Sub RecieveSeek(ByVal Stream As DataStream.Stream) Implements DataStream.IStreamRecieve.RecieveSeek
            Me.RecieveStream(Stream)
        End Sub

        Public ReadOnly Property Name1() As String Implements INamed.Name
            Get
                Return Me.Name
            End Get
        End Property
    End Class

    Public Class libGridCell
        Inherits Windows.Forms.DataGridViewTextBoxCell

        Private mAddress As Long
        Private mData() As Byte
        Private mValue As Single = 0

        Private mControlValue As Single
        Private mControlSwitch As Single
        Private mToBeSet As Boolean = False

        Private mTable As Table

        Sub New()
            MyBase.New()
            Me.Style.SelectionForeColor = Color.White
            Me.Style.Font = My.Settings.Grid_Font
        End Sub
        Public Property toBeSet() As Boolean
            Get
                Return mToBeSet
            End Get
            Set(ByVal value As Boolean)
                mToBeSet = value
                setCell(mValue)
                getCell()
            End Set
        End Property
        Public Property controlBit() As Boolean
            Get
                If getDataValue() >= mControlValue Then
                    Return True
                Else
                    Return False
                End If
            End Get
            Set(ByVal value As Boolean)
                If value Then If Not controlBit Then mValue += mControlSwitch
                If Not value Then If controlBit Then mValue -= mControlSwitch
            End Set
        End Property
        Public Property controlValue() As Double
            Get
                Return mControlValue
            End Get
            Set(ByVal value As Double)
                mControlValue = value
            End Set
        End Property
        Public Property controlSwitch() As Double
            Get
                Return mControlSwitch
            End Get
            Set(ByVal value As Double)
                mControlSwitch = value
            End Set
        End Property
        Public ReadOnly Property Address() As Long
            Get
                Return mAddress
            End Get
        End Property

        Friend Sub setData(ByRef Data() As Byte, ByVal Address As Long, ByRef table As BikiSoft.Table)
            mTable = table
            mAddress = Address
            mData = Data
            getCell()
        End Sub
        Private Sub setCell(ByVal Value As Single)
            Dim f_Value As Single = Value
            f_Value -= mTable.Offset
            f_Value /= mTable.Multiplier
            If mTable.preDivider <> 0 Then f_Value = mTable.preDivider / f_Value
            If Me.controlBit Then f_Value += mControlSwitch
            If Me.toBeSet Then
                If Me.controlBit Then
                    f_Value -= Me.controlSwitch
                    Me.toBeSet = False
                Else
                    f_Value += Me.controlSwitch
                    Me.toBeSet = False
                End If
            ElseIf Me.controlBit Then
                If f_Value < Me.controlValue Then
                    f_Value = Me.controlValue
                End If
            Else
                If f_Value >= Me.controlValue Then
                    f_Value = Me.controlValue - 1
                End If
            End If
            f_Value += mTable.mTrim
            If mTable.ByteSize = 1 Then
                mData(mAddress) = iByte(f_Value)
            ElseIf mTable.ByteSize = 2 Then
                mData(mAddress) = HIBYTE(iShort(f_Value))
                mData(mAddress + 1) = LOBYTE(iShort(f_Value))
            ElseIf mTable.ByteSize = 4 Then
                Array.Copy(System.BitConverter.GetBytes(f_Value), 0, mData, mAddress, 4)
            End If
            mValue = f_Value
        End Sub
        Private Function getDataValue() As Object
            Dim intReturn As Integer
            If mTable.ByteSize = 1 Or mTable.ByteSize = 0 Then
                intReturn = mData(mAddress) - mTable.mTrim
            ElseIf mTable.ByteSize = 2 Then
                intReturn = MAKEWORD(mData(mAddress + 1), mData(mAddress)) - mTable.mTrim
            Else
                Return System.BitConverter.ToSingle(mData, mAddress)
            End If
            Return intReturn
        End Function
        Private Sub getCell()
            Dim tm_Value As Double = getDataValue()
            Dim tm_clr As Color
            Dim tm_clrfg As Color

            Select Case (mTable.Scheme)
                Case DisplayScheme.BK_SCH_LATE
                    'Me.Style.Format = "N1"
                    Me.controlSwitch = 0
                    Me.controlValue = 256
                    If tm_Value >= 129 Then
                        tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(0, 0, 0))
                        tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(191 - (((tm_Value - 128) / 128) * 77), 220 - (((tm_Value - 128) / 128) * 101), 242 - (((tm_Value - 128) / 128) * 62)))
                    Else
                        tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(&HFF, &HFF, &HFF))
                        tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(191 - (((tm_Value) / 128) * 77), 220 - (((tm_Value) / 128) * 101), 242 - (((tm_Value) / 128) * 62)))
                    End If
                Case DisplayScheme.BK_SCH_IGN
                    'Me.Style.Format = "N0"
                    Me.controlSwitch = 128
                    Me.controlValue = 128
                    If tm_Value < 128 Then
                        tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(0, 0, 0))
                        tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(255 - ((tm_Value / 128) * 120), 180 - ((tm_Value / 128) * 129), 90 - ((tm_Value / 128) * 10)))
                    Else
                        tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(&HFF, &HFF, &HFF))
                        tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(215 - (((tm_Value - 128) / 128) * 172), 231 - (((tm_Value - 128) / 128) * 120), 164 - (((tm_Value - 128) / 128) * 116)))
                        tm_Value -= Me.controlSwitch
                    End If
                Case DisplayScheme.BK_SCH_EARLY
                    ' Me.Style.Format = "N1"
                    Me.controlSwitch = 192
                    Me.controlValue = 128
                    If tm_Value < 128 Then
                        tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(0, 0, 0))
                        tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(191 - (((tm_Value) / 128) * 77), 220 - (((tm_Value) / 128) * 101), 242 - (((tm_Value) / 128) * 62)))
                    Else
                        tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(&HFF, &HFF, &HFF))
                        tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(191 - (((tm_Value) / 128) * 77), 220 - (((tm_Value) / 128) * 101), 242 - (((tm_Value) / 128) * 62)))
                        tm_Value -= Me.controlSwitch
                    End If
                Case DisplayScheme.BK_SCH_WORD
                    'If Me.mTable.Multiplier > 1 Then
                    'Me.Style.Format = "N0"
                    'Else
                    'Me.Style.Format = "N1"
                    'End If
                    tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(0, 0, 0))
                    tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(191 - (((tm_Value) / 65535) * 77), 220 - (((tm_Value) / 65535) * 101), 242 - (((tm_Value) / 65535) * 62)))
                Case DisplayScheme.BK_SCH_BYTE
                    ' Me.Style.Format = "N1"
                    tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(0, 0, 0))
                    tm_clr = System.Drawing.ColorTranslator.FromOle(RGB(215 - (((tm_Value - 128) / 128) * 172), 231 - (((tm_Value - 128) / 128) * 120), 164 - (((tm_Value - 128) / 256) * 116)))
                Case DisplayScheme.BK_SCH_SINGLE
                    tm_clrfg = System.Drawing.ColorTranslator.FromOle(RGB(255, 255, 255))
                    tm_clr = Color.Maroon
                    Me.Style.Format = "N3"
                    Me.controlValue = Single.MaxValue

            End Select
            If mTable.preDivider <> 0 Then tm_Value = mTable.preDivider / tm_Value
            tm_Value *= mTable.Multiplier
            tm_Value += mTable.Offset

            Me.mValue = tm_Value
            MyBase.Value = tm_Value
            Me.Style.BackColor = tm_clr
            Me.Style.ForeColor = tm_clrfg
        End Sub

        Public Shadows Property Value() As Single
            Get
                Return Me.mValue
            End Get
            Set(ByVal value As Single)
                setCell(value)
                mValue = value
                MyBase.Value = mValue
                getCell()
            End Set
        End Property
        Public Overrides Function ToString() As String
            Return Format(mValue, Me.Style.Format)
        End Function

        Protected Overrides Sub Paint(ByVal graphics As System.Drawing.Graphics, ByVal clipBounds As System.Drawing.Rectangle, ByVal cellBounds As System.Drawing.Rectangle, ByVal rowIndex As Integer, ByVal cellState As System.Windows.Forms.DataGridViewElementStates, ByVal value As Object, ByVal formattedValue As Object, ByVal errorText As String, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, ByVal paintParts As System.Windows.Forms.DataGridViewPaintParts)
            'graphics.TextRenderingHint = Text.TextRenderingHint.AntiAliasGridFit
            graphics.TextContrast = 8
            MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, mValue, ToString, errorText, cellStyle, advancedBorderStyle, paintParts)
            ' graphics.TextRenderingHint = Text.TextRenderingHint.SystemDefault
        End Sub

        Public Shadows ReadOnly Property ValueType() As System.Type
            Get
                Return GetType(String)
            End Get
        End Property

    End Class
    Public Class LibGridColumn
        Inherits Windows.Forms.DataGridViewColumn

        Sub New()
            MyBase.new(New libGridCell)
            'Me.CellTemplate = New libGridCell
            'Me.DefaultCellStyle = Me.InheritedStyle
            'Me.ValueType = GetType(libGridCell)
        End Sub
        'Public Overrides Property DefaultCellStyle() As System.Windows.Forms.DataGridViewCellStyle
        '    Get
        '        Return MyBase.DefaultCellStyle
        '    End Get
        '    Set(ByVal value As System.Windows.Forms.DataGridViewCellStyle)
        '        MyBase.DefaultCellStyle = value
        '    End Set
        'End Property
        Public Overrides Property CellTemplate() As System.Windows.Forms.DataGridViewCell
            Get
                Return MyBase.CellTemplate
            End Get
            Set(ByVal value As System.Windows.Forms.DataGridViewCell)
                If Not value.GetType.IsAssignableFrom(GetType(libGridCell)) Then
                    Throw New ArgumentException("value not derived from DataGridViewColourPickerCell.")
                Else
                    MyBase.CellTemplate = value
                End If
            End Set
        End Property
    End Class

    Friend Class libProgressbar
        Inherits System.Windows.Forms.UserControl

        Private m_Text As String = ""
        Private m_Font As System.Drawing.Font = Me.DefaultFont
        Private m_TextColour As Color = Color.Red
        Private m_TextAllign As New StringFormat()

        Private mBoarderStyle As libStyle = libStyle.None
        Private mBarColour As Color = Color.Blue
        Private mMax As Single = 100
        Private mMin As Single = 0
        Private mValue As Single

        Friend Enum libStyle As Byte
            None = 0
            FixedSingle = 1
            Fixed3D = 2
            FixedSunken = 3
        End Enum

        Sub New()
            m_TextAllign.Alignment = StringAlignment.Center
            m_TextAllign.LineAlignment = StringAlignment.Center
            Me.DoubleBuffered = True
        End Sub

        Public Sub SetBar(ByVal Value As Single, ByVal Caption As String)
            m_Text = Caption
            If Value < mMin Then
                mValue = mMin
            ElseIf Value > mMax Then
                mValue = mMax
            Else
                mValue = Value
            End If
            Me.Refresh()
        End Sub

        Public Shadows Property Caption() As String
            Get
                Return m_Text
            End Get
            Set(ByVal value As String)
                m_Text = value
                Me.Refresh()
            End Set
        End Property
        Public Property FontColour() As Color
            Get
                Return m_TextColour
            End Get
            Set(ByVal value As Color)
                m_TextColour = value
                Me.Refresh()
            End Set
        End Property
        Public Property BarColour() As Color
            Get
                Return mBarColour
            End Get
            Set(ByVal value As Color)
                mBarColour = value
                Me.Refresh()
            End Set
        End Property
        Public Shadows Property Font() As Font
            Get
                Return m_Font
            End Get
            Set(ByVal value As Font)
                m_Font = value
                Me.Refresh()
            End Set
        End Property
        Public Shadows Property BorderStyle() As libStyle
            Get
                Return mBoarderStyle
            End Get
            Set(ByVal value As libStyle)
                mBoarderStyle = value
                If mBoarderStyle <> libStyle.FixedSunken Then
                    MyBase.BorderStyle = mBoarderStyle
                Else
                    MyBase.BorderStyle = Windows.Forms.BorderStyle.None
                End If
            End Set
        End Property
        Public Shadows Property Doublebuffered() As Boolean
            Get
                Return MyBase.DoubleBuffered
            End Get
            Set(ByVal value As Boolean)
                MyBase.DoubleBuffered = value
            End Set
        End Property

        Public Property TextAllignVertical() As System.Drawing.StringAlignment
            Get
                Return m_TextAllign.Alignment
            End Get
            Set(ByVal value As System.Drawing.StringAlignment)
                m_TextAllign.Alignment = value
                Me.Refresh()
            End Set
        End Property
        Public Property TextAllignHorizontal() As System.Drawing.StringAlignment
            Get
                Return m_TextAllign.LineAlignment
            End Get
            Set(ByVal value As System.Drawing.StringAlignment)
                m_TextAllign.LineAlignment = value
                Me.Refresh()
            End Set
        End Property
        Public Property Minimum() As Single
            Get
                Return mMin
            End Get
            Set(ByVal value As Single)
                If mMax <> value Then
                    mMin = value
                    Me.Refresh()
                End If
            End Set
        End Property
        Public Property Maximum() As Single
            Get
                Return mMax
            End Get
            Set(ByVal value As Single)
                If mMin <> value Then
                    mMax = value
                    Me.Refresh()
                End If
            End Set
        End Property
        Public Property Value() As Single
            Get
                Return mValue
            End Get
            Set(ByVal value As Single)
                If value >= mMin And value <= mMax Then
                    mValue = value
                    Me.Refresh()
                End If
            End Set
        End Property

        Private Delegate Sub RefreshDelegate()
        Public Overrides Sub Refresh()
            If Me.InvokeRequired Then
                Me.Invoke(New RefreshDelegate(AddressOf Refresh))
            Else
                Try
                    MyBase.Refresh()
                Catch ex As System.Exception
                End Try
            End If
        End Sub

        Public Shadows Sub Update()
            If Me.InvokeRequired Then
                Me.Invoke(New RefreshDelegate(AddressOf Update))
            Else
                Try
                    MyBase.Update()
                Catch ex As System.Exception
                End Try
            End If
        End Sub

        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
            On Error Resume Next
            drawBar(e.Graphics)
            drawText(e.Graphics)
        End Sub

        Sub drawText(ByRef g As Graphics)
            g.CompositingQuality = CompositingQuality.HighSpeed
            g.InterpolationMode = InterpolationMode.Default
            If Not m_Font Is Nothing And m_Text <> "" Then

                'Dim f_font As New System.Drawing.Font("Courier New", 9, FontStyle.Regular, GraphicsUnit.Pixel)
                Dim f_Point As New Point

                ' calcualte the clipping point for the rendering of text

                Dim f_split As UInteger = ((Me.mValue - Me.mMin) / (Me.mMax - Me.mMin)) * Me.ClientSize.Width

                Select Case m_TextAllign.Alignment
                    Case StringAlignment.Center
                        f_Point.X = Me.ClientSize.Width / 2
                    Case StringAlignment.Far
                        f_Point.X = Me.ClientSize.Width - 4
                    Case StringAlignment.Near
                        f_Point.X = 4
                End Select
                Select Case m_TextAllign.LineAlignment
                    Case StringAlignment.Center
                        f_Point.Y = Me.ClientSize.Height / 2
                    Case StringAlignment.Far
                        f_Point.Y = Me.ClientSize.Height - 2
                    Case StringAlignment.Near
                        f_Point.Y = 2
                End Select

                Using b As New SolidBrush(m_TextColour)
                    g.Clip = New Region(New Rectangle( _
                        f_split, _
                        0, _
                        Me.ClientSize.Width - f_split, _
                        Me.ClientSize.Height))
                    g.DrawString(m_Text, _
                        m_Font, _
                        b, _
                        f_Point, _
                        m_TextAllign)
                End Using

                If CInt(mBarColour.R) + CInt(mBarColour.B) + CInt(mBarColour.G) > CInt(128 * 3) Then
                    Using b As New SolidBrush(Color.Black)
                        g.Clip = New Region(New Rectangle( _
                            0, _
                            0, _
                            f_split, _
                            Me.ClientSize.Height))
                        g.DrawString(m_Text, _
                             m_Font, _
                             b, _
                             f_Point, _
                             m_TextAllign)
                    End Using
                Else
                    Using b As New SolidBrush(Color.White)
                        g.Clip = New Region(New Rectangle( _
                            0, _
                            0, _
                            f_split, _
                            Me.ClientSize.Height))
                        g.DrawString(m_Text, _
                             m_Font, _
                             b, _
                             f_Point, _
                             m_TextAllign)
                    End Using
                End If

            End If
        End Sub
        Sub drawBar(ByRef g As Graphics)
            If mMax - mMin <> 0 Then
                Dim centerPt As Integer = (mValue - mMin) / (mMax - mMin) * CDbl(Me.ClientSize.Width)
                If centerPt >= Me.ClientSize.Width Then
                    centerPt = Me.ClientSize.Width - 1
                End If

                g.FillRectangle(New SolidBrush(mBarColour), New Rectangle(0, 0, centerPt, Me.ClientSize.Height))
            End If

            g.DrawLine(New Pen(Brightness(Me.BackColor, 75), 1), 0, 0, 0, Me.ClientSize.Height)
            g.DrawLine(New Pen(Brightness(Me.BackColor, 75), 1), 0, 0, Me.ClientSize.Width, 0)
            g.DrawLine(New Pen(Brightness(Me.BackColor, 125), 1), Me.ClientSize.Width - 1, 0, Me.ClientSize.Width - 1, Me.ClientSize.Height)
            g.DrawLine(New Pen(Brightness(Me.BackColor, 125), 1), 0, Me.ClientSize.Height - 1, Me.ClientSize.Width - 1, Me.ClientSize.Height - 1)
        End Sub

    End Class
End Namespace

